package concurrentprogrammingchat.chat;

import concurrentprogrammingchat.tupleserver.TupleProxy;



public class ChatServer {

	//Theses strings are used as the first field of each tuple do identify what kind of tuple we are dealing with.	
	//There are 4 types of Tuples you can add to or get from Tuple Space.
	public static String MSG = "MESSAGE";
	public static String CN = "CHANNELS_NAMES";
	public static String TI = "TUPLESPACE_INFO";
    public static String LASTID = "LASTID";
	
	public static int[] tupleID;
	
	private final TupleProxy tupleProxy;
	private final int rows;
	private final String[] channels;

	//Constructor for creating a ChatServer
    public ChatServer(TupleProxy tp, int rows, String[] channelNames) {
    	tupleProxy = tp;
    	this.rows = rows;
    	this.channels = channelNames;
    	//We use the Tuple Space as a "Database" to store information about this Tuple Proxy
    	//2 types of information are stored. The first is used to get the rows value and the number of channels
    	String[] tupleSpaceInfo = {TI, String.valueOf(tp.getTupleSpaceID()), String.valueOf(channels.length), String.valueOf(rows)};
    	//Indeed we need to know the number of channels to create the pattern of the second tuple, which is used to get the channel's names
    	String[] tupleChannels = new String[channels.length + 2];
    	tupleChannels[0] = CN;
    	tupleChannels[1] = String.valueOf(tp.getTupleSpaceID());
    	for(int i=0;i<channels.length;i++)
    	{
    		tupleChannels[i+2] = channelNames[i];
    	}
    	tp.put(tupleSpaceInfo);
    	tp.put(tupleChannels);
    	
    	//Now we have to initialize each TupleID, one for each channel
    	tupleID = new int[channelNames.length];
    	for(int i=0;i<channels.length;i++){
    		//Here is initialized the Last ID value, which is the value of the current TupleID for each channel.
            String[] initChannel = {LASTID, channels[i], String.valueOf(0)};
            tupleProxy.put(initChannel);
    		tupleID[i] = 0;
    	}
    }

    //Constructor for connecting to a ChatServer
    public ChatServer(TupleProxy tp) {
    	tupleProxy = tp;
    	//Instead of creating and putting the Tuple Information, here we have to get it from the Tuple Space.
    	String[] tupleInfo = {TI, String.valueOf(tupleProxy.getTupleSpaceID()), null, null};
    	tupleInfo = tupleProxy.get(tupleInfo);
    	//Now we have the rows and the amount of channels, so we can get the channel's names from the tuple space
    	rows = Integer.parseInt(tupleInfo[3]);
    	//tupleInfo[2] + 2 = number of channels + 1 for "CN" + 1 for the tuple space ID
    	String[] channelNames = new String[Integer.parseInt(tupleInfo[2]) + 2];
    	channelNames[0] = CN;
    	channelNames[1] = String.valueOf(tupleProxy.getTupleSpaceID());
    	channelNames = tupleProxy.get(channelNames);
    	String[] result = new String[channelNames.length - 2];
    	for(int i=0; i<result.length;i++)
    		result[i] = channelNames[i+2];
    	channels = result;
    	tupleID = new int[channels.length];
    	for(int i=0;i<channels.length;i++)
    		tupleID[i] = 0;
    	//Don't forget to put back once the critical section is over
    	tupleProxy.put(tupleInfo);
    	tupleProxy.put(channelNames);
    }

    public String[] getChannels() {
    	return channels;
    }

    //Called by the UI when a message is sent
    public void writeMessage(String channel, String message) {
    	//We first have to update the corresponding tupleID
    	int index = 0;
    	for(int i=0;i<channels.length;i++)
    		if(channels[i].equals(channel))
    			index = i;
    	tupleID[index] ++;
    	
    	//And also the current ID, which is stored in the Tuple Space
        String[] updateID = {LASTID, channel, null};
        updateID = tupleProxy.get(updateID);
        System.err.println("GOT: " + updateID[2]);
        updateID[2]= String.valueOf((Integer.parseInt(updateID[2]) + 1));
        System.err.println("NOW: " + updateID[2]);
        tupleProxy.put(updateID);

        //Finally we can actually send the message by calling the put() method of tupleProxy, with MSG identifier
    	String[] channelMessage = {MSG, channel, String.valueOf(tupleID[index]), message};
    	tupleProxy.put(channelMessage);
    }

    //Called by the UI when a listener is added
    public ChatListener openConnection(String channel) {
    	ChatListener cl = new ChatListener(tupleProxy, channel);
    	return cl;
    }
}
